﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace Ys.Base.Common
{
  /// <summary>
  ///字符串拓展
  /// </summary>
  public static  class StringExtension
    {

        /// <summary>
        /// 隐藏中间字符串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetHideCentre(this string str)
        {
            if (str.Length > 8)
            {

                return string.Format("{0}***{1}", str.Substring(0, 4), str.Substring(str.Length - 4, 4));
            }
            else if (str.Length > 5)
            {
                return string.Format("{0}***{1}", str.Substring(0, 2), str.Substring(str.Length - 2, 2));
                
            }
            else if (str.Length > 4)
            {
                return string.Format("{0}***{1}", str.Substring(0, 1), str.Substring(str.Length - 1, 1));

            }
            else
            {
                return GetHideHead(str);
            }
        }


        /// <summary>
        /// 去除xml中的Bom头
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static string GetUTF8String( this string val)
        {
            byte[] buffer=Encoding.UTF8.GetBytes(val);
            if (buffer == null)
                return null;

            if (buffer.Length <= 3)
            {
                return Encoding.UTF8.GetString(buffer);
            }

            byte[] bomBuffer = new byte[] { 0xef, 0xbb, 0xbf };

            if (buffer[0] == bomBuffer[0]
                && buffer[1] == bomBuffer[1]
                && buffer[2] == bomBuffer[2])
            {
                return new UTF8Encoding(false).GetString(buffer, 3, buffer.Length - 3);
            }

            return Encoding.UTF8.GetString(buffer);
        }

        /// <summary>
        /// 隐藏头部
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetHideHead(this string str)
        {
            var length = 1;
            length = length > str.Length ? str.Length : length;
            if (str.Length < 4)
            {
                length = 1;
                if (str.Length == 1)
                {
                    return str;
                }

                return "**" + str.Substring(str.Length - length, length);
            }
            length = 4;
            return "****" + str.Substring(str.Length - length, length);


        }
        /// <summary>
        /// 根据正则表达式返回符合条件的字符串
        /// </summary>
        /// <param name="str"></param>
        /// <param name="Pattern"></param>
        public static string GetRegex(this string str, string Pattern) {
            var vallist = str.GetRegexList(Pattern);

            return vallist.Count > 0 ? vallist[0] : "";
        }

        /// <summary>
        /// 根据正则表达式返回符合条件的字符串list
        /// </summary>
        /// <param name="str"></param>
        /// <param name="pattern">正则表达式</param>
        /// <param name="Splitstr">字符串分隔符队列默认  , 回车</param>
        /// <returns></returns>
        public static List<string> GetRegexList(this string str, string pattern, List<char> Splitstr =null) {
            var list = new List<string>();
            if (str == null) {
                return list;
            }
            List<char> _Splitstr =new List<char> { ',','\n',' ' };
            if (Splitstr == null)
            {
                Splitstr = _Splitstr;
            }
            else {
                Splitstr.AddRange(_Splitstr);
            }
            try
            {
                var strlist = new List<string>();
                foreach (var spli in Splitstr) {
                    strlist.AddRange(str.Split(spli).ToList());
                }

                strlist.ForEach(item =>
                {

                    foreach (var match in Regex.Matches(item, pattern))
                    {
                        var val = match.ToString();
                        if (list.IndexOf(val) < 0)
                        {
                            list.Add(val);
                        }
                    }
                });

                
            }
            catch { }

            return list;
        }
        /// <summary>
        /// 移除所有空格包含中间的。
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string TrimAll(this string str) {
           var val= str.Trim().Replace(" ","").Replace(" ","");

            return val;
        }

       
  
        /// <summary>
        /// 用于判断是否为空字符
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool  IsNull(this string s)
        {
            return string.IsNullOrEmpty(s)|| (s.Trim().Length == 0);
        }
        /// <summary>
        /// 判断是否是guid
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsGuid(this string s) {
            return Guid.TryParse(s,out var newgid);
        }

        /// <summary>
        /// 用于判断是否为非空字符
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsNotNull(this string s)
        {
            return !s.IsNull();
        }

        #region 加密算法

        /// <summary>
        /// 将字符串SHA1
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ToSHA1(this string str)
        {
            return SafeTools.SHA1(str).ToLower();
        }

        /// <summary>
        /// 将字符串转换成MD5加密字符串
        /// </summary>
        /// <param name="orgStr"></param>
        /// <returns></returns>
        public static string ToMd5(this string orgStr)
        {
            using (var md5 = MD5.Create())
            {
                var encoding = Encoding.UTF8;
                var encryptedBytes = md5.ComputeHash(encoding.GetBytes(orgStr));
                var sb = new StringBuilder(32);
                foreach (var bt in encryptedBytes)
                {
                    sb.Append(bt.ToString("x").PadLeft(2, '0'));
                }
                return sb.ToString().ToLower();
            }
        }
        #endregion
        /// <summary>
        /// 获取扩展名
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string GetExt(this string s)
        {
            var ret = string.Empty;
            if (!s.Contains('.')) return ret;
            var temp = s.Split('.');
            ret = temp[temp.Length - 1];

            return ret;
        }
        /// <summary>
        /// 验证QQ格式
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsQq(this string s)
        {
            return s.IsNull() || Regex.IsMatch(s, @"^[1-9]\d{4,15}$");
        }

        /// <summary>
        /// 将字符串根据分隔符转换我List<string>
        /// </summary>
        /// <param name="str"></param>
        /// <param name="split">分隔符</param>
        /// <returns></returns>
        public static List<string> ToListString(this string str, char split)
        {
            return new List<string>(str.Split(split));
           
        }

        /// <summary>
        /// 判断是否为有效的Email地址
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsEmail(this string s)
        {
            if (!s.IsNull())
            {
                //return Regex.IsMatch(s,
                //         @"^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))" +
                //         @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$");
                const string pattern = @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$";
                return Regex.IsMatch(s, pattern);
            }
            return false;
        }
        /// <summary>
        /// 判断是否是url
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsUrl(this string s) {
            if (!s.IsNull()) {
                const string pattern = @"^(http://|https://)?((?:[A-Za-z0-9]+-[A-Za-z0-9]+|[A-Za-z0-9]+)\.)+([A-Za-z]+)[/\?\:]?.*$";
                return Regex.IsMatch(s,pattern);
            }
            return false;
        }

        /// <summary>
        /// 验证是否是合法的电话号码
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsPhone(this string s)
        {
            if (!s.IsNull())
            {
                return Regex.IsMatch(s, @"^\+?((\d{2,4}(-)?)|(\(\d{2,4}\)))*(\d{0,16})*$");
            }
            return true;
        }

        /// <summary>
        /// 验证是否是合法的手机号码
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsMobile(this string s)
        {
            if (!s.IsNull())
            {
                return Regex.IsMatch(s, @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
            }
            return false;
        }

        /// <summary>
        /// 验证是否是合法的邮编
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsZipCode(this string s)
        {
            if (!s.IsNull())
            {
                return Regex.IsMatch(s, @"[1-9]\d{5}(?!\d)");
            }
            return true;
        }

        /// <summary>
        /// 验证是否是合法的传真
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsFax(this string s)
        {
            if (!s.IsNull())
            {
                return Regex.IsMatch(s, @"(^[0-9]{3,4}\-[0-9]{7,8}$)|(^[0-9]{7,8}$)|(^\([0-9]{3,4}\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$)");
            }
            return true;
        }

        /// <summary>
        /// 检查字符串是否为有效的int数字
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool Isint(this string val)
        {
            if (IsNull(val))
                return false;
            int k;
            return int.TryParse(val, out k);
        }
        /// <summary>
        /// 检查字符串是否为有效的long数字
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool Islong(this string val)
        {
            if (IsNull(val))
                return false;
            long k;
            return long.TryParse(val, out k);
        }
        /// <summary>
        /// 字符串转数字，未转换成功返回0
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static int ToInt(this string val)
        {
            
            if (IsNull(val))
                return 0;
            int k;
            return int.TryParse(val, out k) ? k : 0;
        }
        /// <summary>
        /// 字符串转 浮点Double
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static double ToDouble(this string val) {
            if (IsNull(val)) {
                return 0; 
            }
            double values;
            return double.TryParse(val, out values) ? values : 0;
        }

        /// <summary>
        /// 将int间隔字符串转换为list<int>
        /// </summary>
        /// <param name="str"></param>
        /// <param name="Split"></param>
        /// <returns></returns>
        public static List<int> ToIntList(this string str, char Split=',')
        {
            return str.Split(Split).strToIntArray().ToList();
        }

        /// <summary>
        /// 判断是否是json字符串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsJson(this string str) {
            try
            {
                System.Text.Json.JsonSerializer.Deserialize<System.Text.Json.JsonElement>(str);
                return true;
            }
            catch {
                return false;
            }
        }

        /// <summary>
        /// 检查字符串是否为有效的INT64数字
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool IsInt64(this string val)
        {
            if (IsNull(val))
                return false;
            long k;
            return long.TryParse(val, out k);
        }

        /// <summary>
        /// 验证是否是身份证
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        public static bool IsCardId(this string ID)
        {
            var r = false;
            if (IsNull(ID))
                r= false;
            if (ID.Length == 15)
            {

                var date = $"19{ID.Substring(6, 2)}-{ID.Substring(8, 2)}-{ID.Substring(10, 2)}";
                DateTime dt;
                return DateTime.TryParse(date,out dt);
            }
            else if (ID.Length == 18)
            {
                var date = $"{ID.Substring(6, 4)}-{ID.Substring(10, 2)}-{ID.Substring(12, 2)}";
                DateTime dt;
                return DateTime.TryParse(date, out dt);
            }
            else { r= false; }

            return r;
        }
        /// <summary>
        /// 从身份证中提取出生年月日 yyyy-MM-dd
        /// </summary>
        /// <param name="IDCard"></param>
        /// <returns></returns>
        public static string GetIdCardBirthday(this string IDCard)
        {
            string BirthDay = null;
            string strYear;
            string strMonth;
            string strDay;
            if (IDCard.Length == 15)
            {
                strYear = IDCard.Substring(6, 2);
                strMonth = IDCard.Substring(8, 2);
                strDay = IDCard.Substring(10, 2);
                BirthDay = "19" + strYear + "-" + strMonth + "-" + strDay;
            }
            if (IDCard.Length == 18)
            {
                strYear = IDCard.Substring(6, 4);
                strMonth = IDCard.Substring(10, 2);
                strDay = IDCard.Substring(12, 2);
                BirthDay = strYear + "-" + strMonth + "-" + strDay;
            }
            return BirthDay;

        }

        /// <summary>
        /// 检查字符串是否为有效的double
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool IsDecimal(this string val)
        {
            if (IsNull(val))
                return false;
            double d;
            return double.TryParse(val, out d);
        }

        /// <summary>
        ///检测字符串是否是时间类型
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool IsDateTime(this string val) {
            if (IsNull(val))
                return false;
            DateTime d;
            return DateTime.TryParse(val,out d);
        }

        /// <summary>
        /// 将时间字符串转为指定格式的字符串  自动判断是否是时间格式，如果不是时间格式则返回原有字符串
        /// </summary>
        /// <param name="val"></param>
        /// <param name="Format"></param>
        /// <returns></returns>
        public static string GetDateTimeFormat(this string val,string Format= "yyyy-MM-dd") {
            if (Format.IsNull())
            {
                Format = "yyyy-MM-dd";
            }

            return val.IsDateTime() ? ((DateTime)val.ToDateTime()).ToString(Format) : val;
        }
        /// <summary>
        /// 获取字符串内包换的数字行字符串
        /// </summary>
        /// <param name="val"></param>
        /// <param name="defaultstr">为空的时候返回的默认字符串</param>
        /// <returns></returns>
        public static string GetIncludeNumber(this string val,string defaultstr="0") {
            if (val.IsNull())
            {
                return defaultstr;
            }
            var str = val.GetRegex("[0-9]{1,100}");
            if (str.IsNull()) {
                str = defaultstr;
            }

            return str;
        }

        /// <summary>
        /// 字符串转时间 非时间返回空
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static DateTime? ToDateTime(this string val) {
            if (val.IsDateTime())
            {
                return DateTime.Parse(val);
            }
            else {
                return null;
            }
        }
        /// <summary>
        /// 按照指定的字符串格式转换为时间 默认 yyyy-MM-dd
        /// </summary>
        /// <param name="val"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        public static DateTime? ToDateTime(this string val,string? format)
        {
            if (format == null)
            {
                return val.ToDateTime();
            }
            DateTime.TryParseExact(val,format,System.Globalization.CultureInfo.InvariantCulture,System.Globalization.DateTimeStyles.AdjustToUniversal,out var gettime);

            return gettime;
        }

        /// <summary>
        /// 将时间类型字符转时间戳 入股不是时间类型则返回0
        /// </summary>
        /// <param name="Val"></param>
        /// <returns></returns>
        public static long ToTimestamp(this string Val) {
            var time = Val.ToDateTime();
            return time != null ? ((DateTime)time).ToTimeStamp() : 0;
        }

        /// <summary>
        /// 从左边截取N个字符
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string GetLeftStr(this string val,int count=0)
        {
            if (count > val.Length)
                return null;

            return val.Substring(0,count);
        }
        /// <summary>
        /// 获取一个字符串在另外一个字符串出现的次数
        /// </summary>
        /// <returns></returns>
        public static int GetincludeCount(this string str,string indexstr) {
            var val = str.Replace(indexstr,null);

            return (str.Length - val.Length) / indexstr.Length;
        }

        /// <summary>
        ///从右边截取N个字符
        /// </summary>
        /// <param name="val"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static string GetRightStr(this string val, int count=0)
        {

            if (count > val.Length)
                return null;

            return val.Substring(val.Length-count, count);

        }
        /// <summary>
        /// 索引字符串是否以指定列表中的字符串开头
        /// </summary>
        /// <param name="val"></param>
        /// <param name="List"></param>
        /// <returns></returns>
        public static bool IndexStartWithList(this string val, List<string> List) {
            var r = false;
            foreach (var item in List) {
                if (val.StartsWith(item))
                {
                    r=true;
                    break;
                }
            }

            return r;
        }

        /// <summary>
        /// 将Base64 解析解出 如果失败则返回null
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string Base64ToString(this string val)
        { string r = null;
            try
            {
                r = Encoding.UTF8.GetString(Convert.FromBase64String(val));
            }
            catch { }

            return r;
        }
        /// <summary>
        /// 判断是否是Base64
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool IsBase64(this string val)
        {
            bool r = false;
            try
            {
               var getr= Encoding.UTF8.GetString(Convert.FromBase64String(val));
                r = true;
            }
            catch { r = false; }

            return r;
        }
        /// <summary>
        /// 字符转换为base64 错误或空字符串返回 null
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string ToBase64(this string val)
        {
            string str = null;
            if (val.IsNull())
                return null;
            try {
               
                str = Convert.ToBase64String(Encoding.UTF8.GetBytes(val));
            }
            catch {
                str = null;
            }

            return str;
        }

        /// <summary>
        /// 获取字符串中的数字字符串
        /// </summary>
        /// <returns></returns>
        public static string GetIntStr(this string val)
        {
            var r = "";
            var clist = new List<char>() {'0','1','2','3','4','5','6','7','8','9' };
            foreach (var v in val)
            {
                if (clist.IndexOf(v) >= 0)
                { 
                    r+=v;
                }
            }
            return r;
        }

    }
}
